home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / sectools / fragrouter / Libnet-0.99b / src / dlpi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-26  |  17.0 KB  |  734 lines

  1. /*
  2.  *  $Id: dlpi.c,v 1.1.1.1 1999/05/18 15:33:42 dugsong Exp $
  3.  *
  4.  *  libnet
  5.  *  dlpi.c - dlpi routines
  6.  *
  7.  *  Copyright (c) 1998, 1999 Mike D. Schiffman <mike@infonexus.com>
  8.  *                           route|daemon9 <route@infonexus.com>
  9.  *  All rights reserved.
  10.  *
  11.  * Copyright (c) 1993, 1994, 1995, 1996, 1997
  12.  *    The Regents of the University of California.  All rights reserved.
  13.  *
  14.  * Redistribution and use in source and binary forms, with or without
  15.  * modification, are permitted provided that: (1) source code distributions
  16.  * retain the above copyright notice and this paragraph in its entirety, (2)
  17.  * distributions including binary code include the above copyright notice and
  18.  * this paragraph in its entirety in the documentation or other materials
  19.  * provided with the distribution, and (3) all advertising materials mentioning
  20.  * features or use of this software display the following acknowledgement:
  21.  * ``This product includes software developed by the University of California,
  22.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  23.  * the University nor the names of its contributors may be used to endorse
  24.  * or promote products derived from this software without specific prior
  25.  * written permission.
  26.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  27.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  28.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  29.  *
  30.  * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
  31.  * University College London.
  32.  */
  33.  
  34.  
  35. #if (HAVE_CONFIG_H)
  36. #include "../include/config.h"
  37. #endif
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40. #ifdef HAVE_SYS_BUFMOD_H
  41. #include <sys/bufmod.h>
  42. #endif
  43. #include <sys/dlpi.h>
  44. #ifdef HAVE_HPUX9
  45. #include <sys/socket.h>
  46. #endif
  47. #ifdef DL_HP_PPA_ACK_OBS
  48. #include <sys/stat.h>
  49. #endif
  50. #include <sys/stream.h>
  51. #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
  52. #include <sys/systeminfo.h>
  53. #endif
  54.  
  55. #ifdef HAVE_HPUX9
  56. #include <net/if.h>
  57. #endif
  58.  
  59. #include <ctype.h>
  60. #ifdef HAVE_HPUX9
  61. #include <nlist.h>
  62. #endif
  63. #include <errno.h>
  64. #include <fcntl.h>
  65. #include <memory.h>
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <stropts.h>
  70. #include <unistd.h>
  71.  
  72. #include "../include/libnet.h"
  73. #include "../include/bpf.h"
  74.  
  75. #include "../include/gnuc.h"
  76. #ifdef HAVE_OS_PROTO_H
  77. #include "../include/os-proto.h"
  78. #endif
  79.  
  80. #ifndef DLPI_DEV_PREFIX
  81. #define DLPI_DEV_PREFIX "/dev"
  82. #endif
  83.  
  84. #define    MAXDLBUF 8192
  85.  
  86. /* Forwards */
  87. static int dlattachreq(int, bpf_u_int32, char *);
  88. static int dlbindack(int, char *, char *);
  89. static int dlbindreq(int, bpf_u_int32, char *);
  90. static int dlinfoack(int, char *, char *);
  91. static int dlinforeq(int, char *);
  92. static int dlokack(int, const char *, char *, char *);
  93. static int recv_ack(int, int, const char *, char *, char *);
  94. static int send_request(int, char *, int, char *, char *, int);
  95. #ifdef HAVE_SYS_BUFMOD_H
  96. static int strioctl(int, int, int, char *);
  97. #endif
  98. #ifdef HAVE_HPUX9
  99. static int dlpi_kread(int, off_t, void *, u_int, char *);
  100. #endif
  101. #ifdef HAVE_DEV_DLPI
  102. static int get_dlpi_ppa(int, const char *, int, char *);
  103. #endif
  104.  
  105. /* XXX Needed by HP-UX (at least) */
  106. static bpf_u_int32 ctlbuf[MAXDLBUF];
  107.  
  108.  
  109. struct link_int *
  110. open_link_interface(char *device, char *ebuf)
  111. {
  112.     register char *cp;
  113.     char *eos;
  114.     register struct link_int *l;
  115.     register int ppa;
  116.     register dl_info_ack_t *infop;
  117.     bpf_u_int32 buf[MAXDLBUF];
  118.     char dname[100];
  119. #ifndef HAVE_DEV_DLPI
  120.     char dname2[100];
  121. #endif
  122.  
  123.     l = (struct link_int *)malloc(sizeof(*l));
  124.     if (l == NULL)
  125.     {
  126.         strcpy(ebuf, ll_strerror(errno));
  127.         return (NULL);
  128.     }
  129.     memset(l, 0, sizeof(*l));
  130.  
  131.     /*
  132.      *  Determine device and ppa
  133.      */
  134.     cp = strpbrk(device, "0123456789");
  135.     if (cp == NULL)
  136.     {
  137.         sprintf(ebuf, "%s missing unit number", device);
  138.         goto bad;
  139.     }
  140.     ppa = strtol(cp, &eos, 10);
  141.     if (*eos != '\0')
  142.     {
  143.         sprintf(ebuf, "%s bad unit number", device);
  144.         goto bad;
  145.     }
  146.  
  147.     if (*device == '/')
  148.     {
  149.         strcpy(dname, device);
  150.     }
  151.     else
  152.     {
  153.         sprintf(dname, "%s/%s", DLPI_DEV_PREFIX, device);
  154.     }
  155. #ifdef HAVE_DEV_DLPI
  156.     /*
  157.      *  Map network device to /dev/dlpi unit
  158.      */
  159.     cp = "/dev/dlpi";
  160.  
  161.     l->fd = open(cp, O_RDWR);
  162.     if (l->fd == -1)
  163.     {
  164.         sprintf(ebuf, "%s: %s", cp, ll_strerror(errno));
  165.         goto bad;
  166.     }
  167.  
  168.     /*
  169.      *  Map network interface to /dev/dlpi unit
  170.      */
  171.     ppa = get_dlpi_ppa(l->fd, dname, ppa, ebuf);
  172.     if (ppa < 0)
  173.     {
  174.         goto bad;
  175.     }
  176. #else
  177.     /*
  178.      *  Try device without unit number
  179.      */
  180.     strcpy(dname2, dname);
  181.     cp = strchr(dname, *cp);
  182.     *cp = '\0';
  183.  
  184.     l->fd = open(dname, O_RDWR);
  185.     if (l->fd == -1)
  186.     {
  187.         if (errno != ENOENT)
  188.         {
  189.             sprintf(ebuf, "%s: %s", dname, ll_strerror(errno));
  190.             goto bad;
  191.         }
  192.  
  193.         /*
  194.          *  Try again with unit number
  195.          */
  196.         l->fd = open(dname2, O_RDWR);
  197.         if (l->fd == -1)
  198.         {
  199.             sprintf(ebuf, "%s: %s", dname2, ll_strerror(errno));
  200.             goto bad;
  201.         }
  202.  
  203.         cp = dname2;
  204.         while (*cp && !isdigit(*cp)) cp++;
  205.         if (*cp) ppa = atoi(cp);
  206.         else
  207.         /*
  208.          *  XXX Assume unit zero
  209.          */
  210.         ppa = 0;
  211.     }
  212. #endif
  213.     /*
  214.      *  Attach if "style 2" provider
  215.      */
  216.     if (dlinforeq(l->fd, ebuf) < 0 || dlinfoack(l->fd, (char *)buf, ebuf) < 0)
  217.     {
  218.         goto bad;
  219.     }
  220.     infop = &((union DL_primitives *)buf)->info_ack;
  221.     if (infop->dl_provider_style == DL_STYLE2 && (dlattachreq(l->fd, ppa, ebuf)
  222.         < 0 || dlokack(l->fd, "attach", (char *)buf, ebuf) < 0))
  223.     {
  224.         goto bad;
  225.     }
  226.  
  227.     /*
  228.      *  Bind HP-UX 9 and HP-UX 10.20
  229.      */
  230. #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) || defined(HAVE_SOLARIS)
  231.     if (dlbindreq(l->fd, 0, ebuf) < 0 || dlbindack(l->fd, (char *)buf, ebuf) < 0)
  232.     {
  233.         goto bad;
  234.     }
  235. #endif
  236.  
  237.     /*
  238.      *  Determine link type
  239.      */
  240.     if (dlinforeq(l->fd, ebuf) < 0 || dlinfoack(l->fd, (char *)buf, ebuf) < 0)
  241.     {
  242.         goto bad;
  243.     }
  244.  
  245.     infop = &((union DL_primitives *)buf)->info_ack;
  246.     switch (infop->dl_mac_type)
  247.     {
  248.         case DL_CSMACD:
  249.         case DL_ETHER:
  250.             l->linktype = DLT_EN10MB;
  251.             break;
  252.         case DL_FDDI:
  253.             l->linktype = DLT_FDDI;
  254.             break;
  255.         default:
  256.             sprintf(ebuf, "unknown mac type 0x%lu", infop->dl_mac_type);
  257.             goto bad;
  258.     }
  259.  
  260. #ifdef    DLIOCRAW
  261.     /*
  262.      *  This is a non standard SunOS hack to get the ethernet header.
  263.      */
  264.     if (strioctl(l->fd, DLIOCRAW, 0, NULL) < 0)
  265.     {
  266.         sprintf(ebuf, "DLIOCRAW: %s", ll_strerror(errno));
  267.         goto bad;
  268.     }
  269. #endif
  270.  
  271.     return (l);
  272. bad:
  273.     free(l);
  274.     return (NULL);
  275. }
  276.  
  277.  
  278. static int
  279. send_request(int fd, char *ptr, int len, char *what, char *ebuf, int flags)
  280. {
  281.     struct strbuf ctl;
  282.  
  283.     ctl.maxlen = 0;
  284.     ctl.len = len;
  285.     ctl.buf = ptr;
  286.  
  287.     if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0)
  288.     {
  289.         sprintf(ebuf, "send_request: putmsg \"%s\": %s", what, ll_strerror(errno));
  290.         return (-1);
  291.     }
  292.     return (0);
  293. }
  294.  
  295. static int
  296. recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf)
  297. {
  298.     union DL_primitives *dlp;
  299.     struct strbuf ctl;
  300.     int flags;
  301.  
  302.     ctl.maxlen = MAXDLBUF;
  303.     ctl.len = 0;
  304.     ctl.buf = bufp;
  305.  
  306.     flags = 0;
  307.     if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0)
  308.     {
  309.         sprintf(ebuf, "recv_ack: %s getmsg: %s", what, ll_strerror(errno));
  310.         return (-1);
  311.     }
  312.  
  313.     dlp = (union DL_primitives *)ctl.buf;
  314.     switch (dlp->dl_primitive)
  315.     {
  316.         case DL_INFO_ACK:
  317.         case DL_PHYS_ADDR_ACK:
  318.         case DL_BIND_ACK:
  319.         case DL_OK_ACK:
  320. #ifdef DL_HP_PPA_ACK
  321.         case DL_HP_PPA_ACK:
  322. #endif
  323.         /*
  324.          *  These are OK
  325.          */
  326.         break;
  327.  
  328.         case DL_ERROR_ACK:
  329.             switch (dlp->error_ack.dl_errno)
  330.             {
  331.                 case DL_BADPPA:
  332.                     sprintf(ebuf, "recv_ack: %s bad ppa (device unit)", what);
  333.                     break;
  334.                 case DL_SYSERR:
  335.                     sprintf(ebuf, "recv_ack: %s: %s",
  336.                         what, ll_strerror(dlp->error_ack.dl_unix_errno));
  337.                     break;
  338.                 case DL_UNSUPPORTED:
  339.                     sprintf(ebuf,
  340.                         "recv_ack: %s: Service not supplied by provider", what);
  341.                     break;
  342.                 default:
  343.                     sprintf(ebuf, "recv_ack: %s error 0x%x", what,
  344.                         (bpf_u_int32)dlp->error_ack.dl_errno);
  345.                     break;
  346.             }
  347.             return (-1);
  348.  
  349.         default:
  350.             sprintf(ebuf, "recv_ack: %s unexpected primitive ack 0x%x ",
  351.                 what, (bpf_u_int32)dlp->dl_primitive);
  352.             return (-1);
  353.     }
  354.  
  355.     if (ctl.len < size)
  356.     {
  357.         sprintf(ebuf, "recv_ack: %s ack too small (%d < %d)",
  358.             what, ctl.len, size);
  359.         return (-1);
  360.     }
  361.     return (ctl.len);
  362. }
  363.  
  364. static int
  365. dlpromiscoffreq(int fd, bpf_u_int32 level, char *ebuf)
  366. {
  367.     dl_promiscon_req_t req;
  368.  
  369.     req.dl_primitive = DL_PROMISCOFF_REQ;
  370.     req.dl_level     = level;
  371.  
  372.     return (send_request(fd, (char *)&req, sizeof(req), "promiscoff", ebuf, 0));
  373. }
  374.  
  375. static int
  376. dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf)
  377. {
  378.     dl_promiscon_req_t req;
  379.  
  380.     req.dl_primitive = DL_PROMISCON_REQ;
  381.     req.dl_level     = level;
  382.  
  383.     return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf, 0));
  384. }
  385.  
  386.  
  387. static int
  388. dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf)
  389. {
  390.     dl_attach_req_t req;
  391.  
  392.     req.dl_primitive = DL_ATTACH_REQ;
  393.     req.dl_ppa       = ppa;
  394.  
  395.     return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf, 0));
  396. }
  397.  
  398. static int
  399. dlbindreq(int fd, bpf_u_int32 sap, char *ebuf)
  400. {
  401.  
  402.     dl_bind_req_t    req;
  403.  
  404.     memset((char *)&req, 0, sizeof(req));
  405.     req.dl_primitive = DL_BIND_REQ;
  406. #ifdef DL_HP_RAWDLS
  407.     req.dl_max_conind = 1;  /* XXX magic number */
  408.     /*
  409.      *  22 is INSAP as per the HP-UX DLPI Programmer's Guide
  410.      */
  411.     req.dl_sap = 22;
  412.     req.dl_service_mode = DL_HP_RAWDLS;
  413. #else
  414.     req.dl_sap = sap;
  415. #ifdef DL_CLDLS
  416.     req.dl_service_mode = DL_CLDLS;
  417. #endif
  418. #endif
  419.     return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf, 0));
  420. }
  421.  
  422.  
  423. static int
  424. dlbindack(int fd, char *bufp, char *ebuf)
  425. {
  426.     return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf));
  427. }
  428.  
  429.  
  430. static int
  431. dlokack(int fd, const char *what, char *bufp, char *ebuf)
  432. {
  433.     return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf));
  434. }
  435.  
  436.  
  437. static int
  438. dlinforeq(int fd, char *ebuf)
  439. {
  440.     dl_info_req_t req;
  441.  
  442.     req.dl_primitive = DL_INFO_REQ;
  443.  
  444.     return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf, RS_HIPRI));
  445. }
  446.  
  447. static int
  448. dlinfoack(int fd, char *bufp, char *ebuf)
  449. {
  450.     return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf));
  451. }
  452.  
  453.  
  454. #ifdef HAVE_SYS_BUFMOD_H
  455. static int
  456. strioctl(int fd, int cmd, int len, char *dp)
  457. {
  458.     struct strioctl str;
  459.     int rc;
  460.  
  461.     str.ic_cmd    = cmd;
  462.     str.ic_timout = -1;
  463.     str.ic_len    = len;
  464.     str.ic_dp     = dp;
  465.     
  466.     rc = ioctl(fd, I_STR, &str);
  467.     if (rc < 0)
  468.     {
  469.         return (rc);
  470.     }
  471.     else
  472.     {
  473.         return (str.ic_len);
  474.     }
  475. }
  476. #endif
  477.  
  478.  
  479. #ifdef DL_HP_PPA_ACK_OBS
  480. /*
  481.  * Under HP-UX 10, we can ask for the ppa
  482.  */
  483. static int
  484. get_dlpi_ppa(register int fd, register const char *device, register int unit,
  485.     register char *ebuf)
  486. {
  487.     register dl_hp_ppa_ack_t *ap;
  488.     register dl_hp_ppa_info_t *ip;
  489.     register int i;
  490.     register u_long majdev;
  491.     dl_hp_ppa_req_t    req;
  492.     struct stat statbuf;
  493.     bpf_u_int32 buf[MAXDLBUF];
  494.  
  495.     if (stat(device, &statbuf) < 0)
  496.     {
  497.         sprintf(ebuf, "stat: %s: %s", device, ll_strerror(errno));
  498.         return (-1);
  499.     }
  500.     majdev = major(statbuf.st_rdev);
  501.  
  502.     memset((char *)&req, 0, sizeof(req));
  503.     req.dl_primitive = DL_HP_PPA_REQ;
  504.  
  505.     memset((char *)buf, 0, sizeof(buf));
  506.     if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf, 0) < 0 ||
  507.         recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (char *)buf, ebuf) < 0)
  508.     {
  509.         return (-1);
  510.     }
  511.  
  512.     ap = (dl_hp_ppa_ack_t *)buf;
  513.     ip = (dl_hp_ppa_info_t *)((u_char *)ap + ap->dl_offset);
  514.  
  515.     for (i = 0; i < ap->dl_count; i++)
  516.     {
  517.         if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit)
  518.         break;
  519.  
  520.         ip = (dl_hp_ppa_info_t *)((u_char *)ip + ip->dl_next_offset);
  521.     }
  522.  
  523.     if (i == ap->dl_count)
  524.     {
  525.         sprintf(ebuf, "can't find PPA for %s", device);
  526.         return (-1);
  527.     }
  528.  
  529.     if (ip->dl_hdw_state == HDW_DEAD)
  530.     {
  531.         sprintf(ebuf, "%s: hardware state: DOWN\n", device);
  532.         return (-1);
  533.     }
  534.     return ((int)ip->dl_ppa);
  535. }
  536. #endif
  537.  
  538. #ifdef HAVE_HPUX9
  539. /*
  540.  * Under HP-UX 9, there is no good way to determine the ppa.
  541.  * So punt and read it from /dev/kmem.
  542.  */
  543. static struct nlist nl[] =
  544. {
  545. #define NL_IFNET 0
  546.     { "ifnet" },
  547.     { "" }
  548. };
  549.  
  550. static char path_vmunix[] = "/hp-ux";
  551.  
  552. /*
  553.  *  Determine ppa number that specifies ifname
  554.  */
  555. static int
  556. get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
  557.     register char *ebuf)
  558. {
  559.     register const char *cp;
  560.     register int kd;
  561.     void *addr;
  562.     struct ifnet ifnet;
  563.     char if_name[sizeof(ifnet.if_name)], tifname[32];
  564.  
  565.     cp = strrchr(ifname, '/');
  566.     if (cp != NULL)
  567.     {
  568.         ifname = cp + 1;
  569.     }
  570.     if (nlist(path_vmunix, &nl) < 0)
  571.     {
  572.         sprintf(ebuf, "nlist %s failed", path_vmunix);
  573.         return (-1);
  574.     }
  575.  
  576.     if (nl[NL_IFNET].n_value == 0)
  577.     {
  578.         sprintf(ebuf, "could't find %s kernel symbol", nl[NL_IFNET].n_name);
  579.         return (-1);
  580.     }
  581.  
  582.     kd = open("/dev/kmem", O_RDONLY);
  583.     if (kd < 0)
  584.     {
  585.         sprintf(ebuf, "kmem open: %s", ll_strerror(errno));
  586.         return (-1);
  587.     }
  588.  
  589.     if (dlpi_kread(kd, nl[NL_IFNET].n_value, &addr, sizeof(addr), ebuf) < 0)
  590.     {
  591.         close(kd);
  592.         return (-1);
  593.     }
  594.     for (; addr != NULL; addr = ifnet.if_next)
  595.     {
  596.         if (dlpi_kread(kd, (off_t)addr, &ifnet, sizeof(ifnet), ebuf) < 0 ||
  597.             dlpi_kread(kd, (off_t)ifnet.if_name,
  598.             if_name, sizeof(if_name), ebuf) < 0)
  599.             {
  600.                 close(kd);
  601.                 return (-1);
  602.             }
  603.             sprintf(tifname, "%.*s%d",
  604.                 (int)sizeof(if_name), if_name, ifnet.if_unit);
  605.             if (strcmp(tifname, ifname) == 0)
  606.             {
  607.                 return (ifnet.if_index);
  608.             }
  609.     }
  610.  
  611.     sprintf(ebuf, "Can't find %s", ifname);
  612.     return (-1);
  613. }
  614.  
  615. static int
  616. dlpi_kread(register int fd, register off_t addr,
  617.     register void *buf, register u_int len, register char *ebuf)
  618. {
  619.     register int cc;
  620.  
  621.     if (lseek(fd, addr, SEEK_SET) < 0)
  622.     {
  623.         sprintf(ebuf, "lseek: %s", ll_strerror(errno));
  624.         return (-1);
  625.     }
  626.     cc = read(fd, buf, len);
  627.     if (cc < 0)
  628.     {
  629.         sprintf(ebuf, "read: %s", ll_strerror(errno));
  630.         return (-1);
  631.     }
  632.     else if (cc != len)
  633.     {
  634.         sprintf(ebuf, "short read (%d != %d)", cc, len);
  635.         return (-1);
  636.     }
  637.     return (cc);
  638. }
  639. #endif
  640.  
  641. /*#include <netinet/if_ether.h>*/
  642. #define ETHERADDRL 6
  643. struct  EnetHeaderInfo
  644. {
  645.     struct ether_addr   DestEtherAddr;
  646.     u_short             EtherFrameType;
  647. };
  648.  
  649.  
  650. int
  651. close_link_interface(struct link_int *l)
  652. {
  653.     return (close(l->fd));
  654. }
  655.  
  656.  
  657. struct EnetHeaderInfo ArpHeader =
  658. {
  659.     {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, ETHERTYPE_ARP
  660. };
  661.  
  662.  
  663. int
  664. write_link_layer(struct link_int *l, const u_char *device, u_char *buf, int len)
  665. {
  666.     struct strbuf data, ctl;
  667.     union DL_primitives *dlp;
  668.     int c;
  669.     struct EnetHeaderInfo *EnetHeaderInfoP;
  670.  
  671.     dlp = (union DL_primitives*) ctlbuf;
  672.     dlp->unitdata_req.dl_primitive        = DL_UNITDATA_REQ;
  673.     dlp->unitdata_req.dl_priority.dl_min  = 0;
  674.     dlp->unitdata_req.dl_priority.dl_max  = 0;
  675.     dlp->unitdata_req.dl_dest_addr_length = (sizeof(struct ether_addr) +
  676.                                             sizeof(u_short));
  677.     dlp->unitdata_req.dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE;
  678.  
  679.     EnetHeaderInfoP = (struct EnetHeaderInfo *)(ctlbuf + DL_UNITDATA_REQ_SIZE);
  680.     memcpy(EnetHeaderInfoP, (char *)&(ArpHeader), (sizeof(struct ether_addr) +
  681.                                                   sizeof(u_short)));
  682.  
  683.     /* Send it */
  684.     ctl.len = DL_UNITDATA_REQ_SIZE + sizeof (struct EnetHeaderInfo);
  685.     ctl.buf = (char *)dlp;
  686.  
  687.     data.maxlen = len;
  688.     data.len    = len;
  689.     data.buf    = buf;
  690.  
  691.     c = putmsg(l->fd, NULL, &data, 0);
  692.     if (c == -1)
  693.     {
  694. #if (__DEBUG)
  695.         fprintf(stderr, "write_link_layer: (%s)\n", strerror(errno));
  696. #endif
  697.         return (-1);
  698.     }
  699.     return (len);
  700. }
  701.  
  702.  
  703. struct ether_addr *
  704. get_hwaddr(struct link_int *l, const u_char *device, char *ebuf)
  705. {
  706.     char    buf[2048];
  707.     union DL_primitives *dlp;
  708.     struct ether_addr *eap;
  709.  
  710.     dlp = (union DL_primitives*) buf;
  711.  
  712.     dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
  713.     dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR;
  714.  
  715.     if (send_request(l->fd, (char *)dlp, DL_PHYS_ADDR_REQ_SIZE, "physaddr",
  716.                     ebuf, 0) < 0)
  717.     {
  718.         sprintf(ebuf, "get_hwaddr %s", strerror(errno));
  719.         return (NULL);
  720.     }
  721.     if (recv_ack(l->fd, DL_PHYS_ADDR_ACK_SIZE, "physaddr", (char *)dlp, ebuf)
  722.         < 0)
  723.     {
  724.         sprintf(ebuf, "get_hwaddr %s", strerror(errno));
  725.         return (NULL);
  726.     }
  727.  
  728.     eap = (struct ether_addr *)
  729.         ((char *) dlp + dlp->physaddr_ack.dl_addr_offset);
  730.     return (eap);
  731. }   
  732.  
  733. /* EOF */
  734.